﻿using System;
using System.Collections.Concurrent;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;

namespace FastIM
{
    /// <summary>
    /// 包含WebSocket和客戶端标识的类
    /// </summary>
    public class ImSession
    {
        public WebSocket socket;
        public string clientId;
        public ClientMetaData clientMetaData;
        public ImSession(string clientId, WebSocket socket, ClientMetaData clientMetaData)
        {
            this.socket = socket;
            this.clientId = clientId;
            this.clientMetaData = clientMetaData;
        }
    }
    /// <summary>
    /// Websocket工厂类，用来存取连接到當前服务器server的Websocket实例。
    /// </summary>
    public class ImSessionFactory
    {
        //存储用户唯一标识和用戶登录的多端WebSocket实例，运行一个用户多端登录
        ConcurrentDictionary<string, ConcurrentDictionary<string, ImSession>> _clients = new ConcurrentDictionary<string, ConcurrentDictionary<string, ImSession>>();
        private static ImSessionFactory _instance;
        /// <summary>
        /// 获取工厂实例
        /// </summary>
        /// <returns></returns>
        public static ImSessionFactory Instance()
        {
            if (_instance == null) _instance = new ImSessionFactory();
            return _instance;
        }
        /// <summary>
        /// 当前服务的用户数量
        /// </summary>
        public int Count => _clients.Count;
        /// <summary>
        /// 当前服务器存储客户端对应设备的WebSocket
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="deviceId"></param>
        /// <param name="ws"></param>
        /// <returns></returns>
        public ConcurrentDictionary<string, ImSession> Add(string clientId, string deviceId, ImSession cws)
        {
            var wslist = _clients.GetOrAdd(clientId, cliid => new ConcurrentDictionary<string, ImSession>());
            wslist.TryAdd(deviceId, cws);//一个用户可以有多个WebSocket,可以用来表示一个用户可以多端登录
            return wslist;
        }
        /// <summary>
        /// 获取客户端所有登录的设备
        /// </summary>
        /// <param name="clientId"></param>
        /// <returns>无客户端对应设备返回falsel</returns>
        public bool Get(string clientId, out ConcurrentDictionary<string, ImSession> devicewebSockets)
        {
            return _clients.TryGetValue(clientId, out devicewebSockets);
        }
        /// <summary>
        /// 判断用户的某个设备是否已经登录
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="deviceId"></param>
        /// <returns></returns>
        public bool Exist(string clientId, string deviceId)
        {
            if(Get(clientId,out var devicewebSockets))
            {
                return devicewebSockets.ContainsKey(deviceId);
            }
            return false;          
        }
        /// <summary>
        /// 删除客户端所有设备WebSocket
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="devicewebSockets"></param>
        /// <returns></returns>
        public bool Remove(string clientId, out ConcurrentDictionary<string, ImSession> devicewebSockets)
        {
            return _clients.TryRemove(clientId, out devicewebSockets);
        }
        /// <summary>
        /// 删除客户端对应设备的WebSocket
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="deviceId"></param>
        /// <param name="cws"></param>
        /// <returns></returns>
        public bool Remove(string clientId, string deviceId, out ImSession cws)
        {
            if (Get(clientId, out var devicewebSockets)) return devicewebSockets.TryRemove(deviceId, out cws);
            cws = null;
            return false;
        }
        /// <summary>
        /// 判断客户端是否有设备连接
        /// </summary>
        /// <param name="clientId"></param>
        /// <returns></returns>
        public bool Any(string clientId)
        {
            if (_clients.TryGetValue(clientId, out var devices)) return devices.Any();
            return false;
        }
        /// <summary>
        /// 是否包含客户端
        /// </summary>
        /// <param name="clientId"></param>
        /// <returns></returns>
        public bool ContainsKey(string clientId)
        {        
            return _clients.ContainsKey(clientId);
        }
        /// <summary>
        /// 清空当前服务器所有客户端
        /// </summary>
        public void Clear()
        {
            _clients.Clear();
        }
        /// <summary>
        /// 返回所有客户端
        /// </summary>
        /// <returns></returns>
        public ConcurrentDictionary<string, ConcurrentDictionary<string, ImSession>> All()
        {
            return _clients;
        }
    }
}
